<template>
  <div class="chat-wrapper">
    <div v-if="friend" class="chat" @mouseenter="clearMsgCount">
      <div class="header">
        <div class="photo">
          <img v-if="friend.photo" :src="friend.photo" />
        </div>
        <div class="username">{{friend.username}}</div>
        <div class="username" v-if="typing && friend.id === fromID">输入中...</div>
      </div>
      <div class="chat-list-wrapper">
        <div class="chat-item" v-for="(msgObj,index) in messages" :key="msgObj.msg + index">
          <!-- 我发送的 -->
          <div v-if="msgObj.account === account" class="to">
            <div class="message">
              <a href="javascript:;">{{msgObj.time}}</a>
              <div v-if="msgObj.type === 'string'" class="text">{{msgObj.msg}}</div>
              <img v-if="msgObj.type === 'image'" class="msg-image" :src="msgObj.msg" />
            </div>
            <div class="userinfo">
              <div class="photo">
                <img :src="photo" alt="">
              </div>
              <div class="username">{{username}}</div>
            </div>
          </div>

          <!-- 别人发送给我的 -->
          <div v-else class="from">
            <div class="userinfo">
              <div class="photo">
                <img :src="friend.photo" />
              </div>
              <div class="username">{{friend.username}}</div>
            </div>
            <div class="message">
              <a href="javascript:;">{{msgObj.time}}</a>
              <div v-if="msgObj.type === 'string'" class="text">{{msgObj.msg}}</div>
              <img v-if="msgObj.type === 'image'" class="msg-image" :src="msgObj.msg" />

            </div>
          </div>
        </div>

      </div>

      <div class="send-wrapper">
        <div class="send-bar-oper">
          <div class="oper-item">
            <el-tooltip content="表情" placement="top">

              <el-popover placement="top" :width="400" :height="300" trigger="click">
                <template #reference>
                  😀
                </template>
                <div class="emo-wrapper">
                  <div class="emo-item" v-for="(emo,index) in emos" :key="index" @click="sendEmo(emo)">{{emo}}</div>
                </div>
              </el-popover>
            </el-tooltip>
          </div>
          <div class="oper-item" @click="uploadFile">
            <el-tooltip content="发送图像" placement="top">
              <el-icon>
                <Document />
              </el-icon>
            </el-tooltip>
          </div>
        </div>
        <div class="send-box">
          <textarea id="textarea" v-model="sendMsgText" type="textarea" @focus="sendTextFocus" @blur="sendTextBlur"></textarea>
          <button @click="sendMsg">发送消息</button>
        </div>
      </div>

    </div>
    <div v-else class="no-data">
      请选择聊天对象
    </div>
  </div>
</template>

<script>
/* 
friend
当前聊天的人或者群组
{
  type: 'friend' | 'group' friend: 好友 group: 群组
  info: {
    id: 好友id | 群组id 用于聊天
    photo: 头像
    username: 用户名
  }
}


fromMsgList:

{
  msg: '你好吗',
  account: '发消息用户的id'
}
*/
// import { createUserSocket } from '../utils/socket'
export default {
  name: 'Chat',
  props: {
    friend: {
      type: Object,
      default: () => null
    },
    socketconn: {
      type: Object,
      default: () => null
    }
  },
  watch: {
    'friend.id'(newVal) {
      if (newVal) {
        const chatCache = JSON.parse(this.$storage.getItem('chat_cache'));
        if (chatCache && chatCache[this.account] && chatCache[this.account][newVal] && Array.isArray(chatCache[this.account][newVal])) {
          this.messages = chatCache[this.account][newVal];
        } else {
          this.messages = [];
          if (chatCache) {
            if (!chatCache[this.account]) {
              chatCache[this.account] = {};
            }
            chatCache[this.account][newVal] = this.messages;
            this.$storage.setItem('chat_cache', JSON.stringify(chatCache));
          } else {
            const newCahtCache = {};
            if (!newCahtCache[this.account]) {
              newCahtCache[this.account] = {};
            }
            newCahtCache[this.account][newVal] = this.messages;
            this.$storage.setItem('chat_cache', JSON.stringify(newCahtCache));
          }
        }
        setTimeout(() => {
          document.getElementById('textarea').focus();
          this.scrollToEnd();
        }, 100);
      }
    },
    socketconn(newVal) {
      if (newVal) {
        this.socket = newVal;
        this.socketHandler()
      }
    }
  },
  data() {
    return {
      userInfo: {},
      sendMsgText: '',
      account: '',
      username: '',
      messages: [],
      cache: {},
      socket: null,
      photo: '',
      msgCountObj: {},
      typing: false,
      emo: '😀 😁 😂 🤣 😃 😄 😅 😆 😉 😊 😋 😎 😍 😘 😗 😙 😚 🙂 🤗 🤩 🤔 🤨 😐 😑 😶 🙄 😏 😣 😥 😮 🤐 😯 😪 😫 😴 😌 😛 😜 😝 🤤 😒 😓 😔 😕 🙃 🤑 😲 ☹️ 🙁 😖 😞 😟 😤 😢 😭 😦 😧 😨 😩 🤯 😬 😰 😱 😳 🤪 😵 😡 😠 🤬 😷 🤒 🤕 🤢 🤮 🤧 😇 🤠 🤡 🤥 🤫 🤭 🧐 🤓 😈 👿 👹 👺 💀 👻 👽 🤖 * 😺 😸 😹 😻 😼 😽 🙀 😿 😾',
      emos: [],
      fromID: ''
    }
  },
  mounted() {
    this.getUserInfo();
    this.spliceEmo()
    setTimeout(() => {
      this.scrollToEnd();
    }, 100);
    this.$bus.subscriber('update_user_info', () => {
      this.getUserInfo();
    })
    window.addEventListener('keydown', (ev) => {
      const e = ev || window.event,
        keyCode = e.keyCode,
        shiftKey = e.shiftKey;
      if (shiftKey && keyCode == 13) {
        this.sendMsg();
      }
    })
  },
  methods: {
    uploadFile() {
      const oInput = document.createElement('input');
      oInput.type = 'file';
      oInput.accept = '';
      const handlerFn = (ev) => {
        const e = ev || window.event,
          tar = e.target || e.srcElement,
          file = tar.files[0];
        if (!file.type.includes('image')) {
          alert('只能发送图像数据')
          return;
        }

        if (file.size > 1024 * 1024 * 2) {
          alert('发送的图像文件，不能超过2M')
          return;
        }
        const fileReader = new FileReader();
        fileReader.readAsDataURL(file);
        fileReader.onload = (res) => {
          this.sendMsgText = res.target.result;
          this.sendMsg(null, 'image');
          document.body.removeChild(oInput);
          oInput.removeEventListener('change', handlerFn, false);
        }
      }
      oInput.addEventListener('change', handlerFn, false)
      oInput.style.display = 'none';
      document.body.appendChild(oInput);
      oInput.click();

    },
    spliceEmo() {
      this.emos = this.emo.split(' ');
    },
    getUserInfo() {
      console.log(this.$storage);
      this.userInfo = JSON.parse(this.$storage.getItem('userinfo'));
      this.account = this.userInfo && this.userInfo?.id;
      this.username = this.userInfo && this.userInfo?.username;
      this.photo = this.userInfo.photo;
    },
    sendTextBlur() {
      this.socket && this.socket.emit('typing', JSON.stringify({
        from: this.account,// 发送者
        to: this.friend.id, // 接收者
        type: 'stopTyping'
      }));
    },
    sendTextFocus() {
      this.socket && this.socket.emit('typing', JSON.stringify({
        from: this.account,// 发送者
        to: this.friend.id, // 接收者
        type: 'typing'
      }));
    },
    clearMsgCount() {
      this.$emit('clearMsgCount', this.friend.id);
    },
    socketHandler() {
      // typing 输入中
      this.socket.on('typingreceive', (data) => {
        const { type, from } = JSON.parse(data);
        this.fromID = from;
        console.log('typingreceive', data);
        if (type === 'typing') {
          this.typing = true;
        } else {
          this.typing = false;
        }
      })
      this.socket.on('receive', (data) => {
        const dataObj = JSON.parse(data);
        if (dataObj.from === 'server') {
          this.socket.emit('online', JSON.stringify({
            account: this.account
          }));
        } else {
          const { from, time } = dataObj;
          const chatCache = JSON.parse(this.$storage.getItem('chat_cache'));
          if (chatCache && chatCache[this.account] && chatCache[this.account][from] && Array.isArray(chatCache[this.account][from])) {
            const isExits = chatCache[this.account][from].filter(item => {
              return item.time === time;
            }).length > 0;
            if (!isExits) {
              if (this.msgCountObj[from]) {
                this.msgCountObj[from]++;
              } else {
                this.msgCountObj[from] = 1;
              }
              this.$emit('msgcount', this.msgCountObj);
              if (!chatCache[this.account]) {
                chatCache[this.account] = {};
              }
              chatCache[this.account][from].push(dataObj);
              if (this.friend && this.friend.id && this.friend.id === from) {
                this.messages = chatCache[this.account][from];
              }
              this.$storage.setItem('chat_cache', JSON.stringify(chatCache));
            }
          } else {
            if (this.msgCountObj[from]) {
              this.msgCountObj[from]++;
            } else {
              this.msgCountObj[from] = 1;
            }
            this.$emit('msgcount', this.msgCountObj);
            const chatCache = {
              [this.account]: {
                [from]: []
              }
            };
            chatCache[this.account][from].push(dataObj);
            if (this.friend && this.friend.id && this.friend.id === from) {
              this.messages = chatCache[from];
            }
            this.$storage.setItem('chat_cache', JSON.stringify(chatCache));
          }
          setTimeout(() => {
            this.scrollToEnd();
          }, 100);
        }

      })
    },
    sendEmo(emo) {
      this.sendMsgText += emo;
      // this.sendMsg();
    },
    sendMsg(ev, type = 'string') {
      // 发送消息
      if (!this.sendMsgText.trim()) {
        this.sendMsgText = '';
        alert('不可以发送空白消息')
        return;
      }
      const curDate = this.$utils.getCurentDate();
      if (this.socket) {
        this.socket.emit('chat', JSON.stringify({
          msg: this.sendMsgText.trim(),
          account: this.friend.id,
          time: curDate,
          type
        }));
      }

      const chatCache = JSON.parse(this.$storage.getItem('chat_cache'));
      if (chatCache && chatCache[this.account] && chatCache[this.account][this.friend.id] && Array.isArray(chatCache[this.account][this.friend.id])) {
        chatCache[this.account][this.friend.id].push({
          msg: this.sendMsgText.trim(),
          account: this.account,
          time: curDate,
          type
        });
        this.messages = chatCache[this.account][this.friend.id];
        this.$storage.setItem('chat_cache', JSON.stringify(chatCache));
      } else {
        chatCache[this.account][this.friend.id] = [];
        chatCache[this.account][this.friend.id].push({
          msg: this.sendMsgText.trim(),
          account: this.account,
          time: curDate,
          type
        });
        this.messages = chatCache[this.friend.id];
        this.$storage.setItem('chat_cache', JSON.stringify(chatCache));
      }
      this.sendMsgText = '';
      setTimeout(() => {
        this.scrollToEnd();
      }, 100);
    },
    // 始终保持滚动条在最底部
    scrollToEnd() {
      const chatListWrapper = document.getElementsByClassName('chat-list-wrapper')[0];
      if (chatListWrapper) {
        chatListWrapper.scrollTop = chatListWrapper.scrollHeight;
      }
    }
  }
}
</script>

<style scoped>
.chat-wrapper {
  width: 80%;
  height: 100%;
  background-color: rgb(160, 152, 152);
}

.chat {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.chat .header {
  position: relative;
  width: 100%;
  height: 60px;
  background-color: rgb(177, 172, 172);
  display: flex;
  align-items: center;
}

.chat .header .photo {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: rgb(255, 255, 255);
  margin-left: 20px;
  border: 1px solid rgb(255, 255, 255);
  overflow: hidden;
}
.chat .header .photo img {
  width: 100%;
  height: 100%;
}

.chat .header .username {
  margin-left: 10px;
  font-size: 20px;
  color: rgb(255, 255, 255);
  font-size: 12px;
}
.chat .header .online {
  margin-left: 20px;
  font-size: 20px;
  color: rgb(255, 255, 255);
  font-size: 12px;
}

.chat .header .close {
  position: absolute;
  right: 20px;
  font-size: 20px;
  color: rgb(255, 0, 0);
  font-weight: 900;
  cursor: pointer;
}

.chat .chat-list-wrapper {
  width: 100%;
  flex: 1;
  background-color: rgb(255, 255, 255);
  overflow: hidden;
  overflow-y: auto;
  transition: all 1s ease-in-out;
}

.chat .chat-list-wrapper .chat-item {
  display: flex;
  width: 100%;
  min-height: 60px;
  background-color: rgb(255, 255, 255);
  padding-left: 10px;
  padding-right: 10px;
}
.chat-item .to,
.from {
  width: 100%;
  height: 100%;
  display: flex;
}
.chat-item .to .message {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  flex: 1;
  text-align: right;
  margin-right: 10px;
  word-break: break-all;
  text-align: left;
  margin-right: 10px;
}
.chat-item .from .message {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  flex: 1;
  text-align: right;
  margin-right: 10px;
  word-break: break-all;
  text-align: left;
  margin-left: 10px;
}

.message a {
  font-size: 10px;
  margin-top: 5px;
  cursor: default;
}

.message .msg-image {
  margin-top: 10px;
  height: 200px;
  object-fit: contain;
  cursor: pointer;
  margin-bottom: 10px;
}

.chat-item .userinfo {
  display: flex;
  flex-direction: column;
  width: 40px;
  height: 60px;
}

.chat-item .userinfo .photo {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 1px solid rgb(0, 0, 0);
  overflow: hidden;
}

.chat-item .userinfo .photo img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.chat-item .userinfo .username {
  height: 20px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 10px;
}

.send-wrapper {
  width: 100%;
  height: 150px;
  display: flex;
  flex-direction: column;
  border-top: 1px solid rgb(160, 157, 157);
  background-color: #ffffff;
}

.send-bar-oper {
  height: 20px;
  width: 100%;
  display: flex;
  justify-content: flex-start;
  align-items: center;
  padding-left: 10px;
}

.oper-item {
  cursor: pointer;
  margin-right: 10px;
}

.oper-item .el-icon {
  width: 30px;
  height: 30px;
  line-height: 30px;
  font-size: 20px;
}

.emo-wrapper {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  height: 300px;
  overflow: hidden;
  overflow-y: auto;
}

.emo-wrapper .emo-item {
  width: 30px;
  height: 30px;
  font-size: 20px;
}

.send-box {
  position: relative;
  width: 100%;
  height: 100px;
  flex: 1;
  background-color: yellow;
}
.send-box textarea {
  width: 100%;
  height: 100%;
  outline: none;
  border: none;
  padding-left: 10px;
}
.send-box button {
  position: absolute;
  bottom: 10px;
  right: 10px;
}

.no-data {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #ffffff;
}
</style>